#pragma comment(lib, "glaux.lib") // Compiler directive (works in MS environment) to include the GLaux library.

#include <GL/glut.h>
#include <gl/glaux.h> // Header file for the GLaux library.  
#include <math.h>
#include <iostream.h>
#include <GL/glext.h>
#include <vector>
#include "AITArea.h"
#include "Road.h"

using namespace std;

static int NONE_ATYPE = 0;
static int ENTER_ATYPE = 1;

static int A1_ATYPE = 2;//test if have many area
static int A2_ATYPE = 3;//test if have many area
static int A3_ATYPE = 4;//test if have many area
static int A4_ATYPE = 5;//test if have many area
static int A5_ATYPE = 6;//test if have many area
static int A6_ATYPE = 7;//test if have many area
//static int A7_ATYPE = 8;//test if have many area

static int NUMBER_OF_TYPE = 8;//6;//2;//3; // don't use now

//Enter Area
static float Enter_WArea = 30.0; 
static float Enter_HArea = 30.0;
static float X_Pos_Enter_Area = 60.0;
static float Y_Pos_Enter_Area = -30.0;
static float Z_Pos_Enter_Area = 0.0;

//Area1 for test if have many area
static float A1_WArea = Enter_WArea; 
static float A1_HArea = Enter_HArea;
static float X_Pos_A1_Area = X_Pos_Enter_Area-Enter_WArea;
static float Y_Pos_A1_Area = Y_Pos_Enter_Area+(Enter_HArea*0.20);
static float Z_Pos_A1_Area = 0.0;

//Area2 for test if have many area
static float A2_WArea = A1_WArea; 
static float A2_HArea = A1_HArea;
static float X_Pos_A2_Area = X_Pos_A1_Area-A1_WArea;
static float Y_Pos_A2_Area = Y_Pos_A1_Area;
static float Z_Pos_A2_Area = 0.0;

//Area3 for test if have many area
static float A3_WArea = A2_WArea; 
static float A3_HArea = A2_HArea;
static float X_Pos_A3_Area = X_Pos_A2_Area-A2_WArea;
static float Y_Pos_A3_Area = Y_Pos_A2_Area;
static float Z_Pos_A3_Area = 0.0;

//Area4 for test if have many area
static float A4_WArea = A3_WArea; 
static float A4_HArea = A3_HArea;
static float X_Pos_A4_Area = X_Pos_A3_Area;
static float Y_Pos_A4_Area = Y_Pos_A3_Area+A3_HArea;
static float Z_Pos_A4_Area = 0.0;

//Area5 for test if have many area
static float A5_WArea = A4_WArea; 
static float A5_HArea = A4_HArea;
static float X_Pos_A5_Area = X_Pos_A4_Area+(A4_WArea*0.10);
static float Y_Pos_A5_Area = Y_Pos_A4_Area+A4_HArea;
static float Z_Pos_A5_Area = 0.0;

//Area6 for test if have many area
static float A6_WArea = A5_WArea; 
static float A6_HArea = A5_HArea;
static float X_Pos_A6_Area = X_Pos_A5_Area+A5_WArea;
static float Y_Pos_A6_Area = Y_Pos_A5_Area;
static float Z_Pos_A6_Area = 0.0;

/*
//Area7 for test if have many area
static float A7_WArea = 3.0; 
static float A7_HArea = 3.0;
static float X_Pos_A7_Area = X_Pos_A7_Area;
static float Y_Pos_A7_Area = Y_Pos_A7_Area+3.0;
static float Z_Pos_A7_Area = 0.0;
*/


////////////////////////////////////////////////////
// Road
///////////////////////////////////////////////////

static float EnterRoadMPoints[42] = 
{
		20.0 , 0.0 , 0.0,
		0.0, 20.0 , 0.0,
		-2.0, 23.0, 0.0,
		-7.0, 27.0, 0.0,
		-10.0, 30.0, 0.0,
		-20.0, 32.0, 0.0,
		-30.0, 28.0, 0.0,
		-60.0, 20.0, 0.0,
		-65.0, 18.0, 0.0,
		-75.0, 19.0, 0.0,
		-80.0, 22.0, 0.0,
		-80.0, 85.0, 0.0,
		-75.0, 90.0, 0.0,
		-30.0, 90.0, 0.0,
};
static int EnterNumberPoint = 14;
static int WEnterR =5;
static float Leftcontrols[42]=
{
		20.0 , 0.0 , 0.0,
		0.0, 20.0 , 0.0,
		-2.0, 23.0, 0.0,
		-7.0, 27.0, 0.0,
		-10.0, 30.0, 0.0,
		-20.0, 32.0, 0.0,
		-30.0, 28.0, 0.0,
		-60.0, 20.0, 0.0,
		-65.0, 18.0, 0.0,
		-75.0, 19.0, 0.0,
		-80.0, 22.0, 0.0,
		-80.0, 85.0, 0.0,
		-75.0, 90.0, 0.0,
		-30.0, 90.0, 0.0,
};
static float Rightcontrols[42] = {
		20.0 , 0.0 , 0.0,
		0.0, 20.0 , 0.0,
		-2.0, 23.0, 0.0,
		-7.0, 27.0, 0.0,
		-10.0, 30.0, 0.0,
		-20.0, 32.0, 0.0,
		-30.0, 28.0, 0.0,
		-60.0, 20.0, 0.0,
		-65.0, 18.0, 0.0,
		-75.0, 19.0, 0.0,
		-80.0, 22.0, 0.0,
		-80.0, 85.0, 0.0,
		-75.0, 90.0, 0.0,
		-30.0, 90.0, 0.0,
};

///////////////////////////////////////////////////

//Control Rotate Space
static float Xangle = 0.0, Yangle = 0.0, Zangle = 0.0; // Angles to rotate.

static int isWire = 1; // Is wireframe?

// Vector of AIT Area.
vector<AITArea> areas;

// Iterator to traverse a AIT Area array.
vector<AITArea>::iterator areasIterator;

// Vector of AIT Road.
vector<Road> roads;

// Iterator to traverse a AIT Road array.
vector<Road>::iterator roadsIterator;


void drawAITAreas(void)
{
	//AITArea area;
	//area.Intial(5.0,5.0,ENTER_ATYPE);
	//area.Render(0.0,0.0,0.0);
	areasIterator = areas.begin();
	while(areasIterator != areas.end())
	{
		if(areasIterator->getAType() == ENTER_ATYPE)
		{
			areasIterator->Render(X_Pos_Enter_Area,Y_Pos_Enter_Area,Z_Pos_Enter_Area);
		}else if(areasIterator->getAType() == A1_ATYPE){
			areasIterator->Render(X_Pos_A1_Area,Y_Pos_A1_Area,Z_Pos_A1_Area);
		}else if(areasIterator->getAType() == A2_ATYPE){
			areasIterator->Render(X_Pos_A2_Area,Y_Pos_A2_Area,Z_Pos_A2_Area);
		}else if(areasIterator->getAType() == A3_ATYPE){
			areasIterator->Render(X_Pos_A3_Area,Y_Pos_A3_Area,Z_Pos_A3_Area);
		}else if(areasIterator->getAType() == A4_ATYPE){
			areasIterator->Render(X_Pos_A4_Area,Y_Pos_A4_Area,Z_Pos_A4_Area);
		}else if(areasIterator->getAType() == A5_ATYPE){
			areasIterator->Render(X_Pos_A5_Area,Y_Pos_A5_Area,Z_Pos_A5_Area);
		}else if(areasIterator->getAType() == A6_ATYPE){
			areasIterator->Render(X_Pos_A6_Area,Y_Pos_A6_Area,Z_Pos_A6_Area);
		}/*else if(areasIterator->getAType() == A7_ATYPE){
			areasIterator->Render(X_Pos_A7_Area,Y_Pos_A7_Area,Z_Pos_A7_Area);
		}*/else{
			cout<< "Area Type Have NONE TYPE at "<< areasIterator <<":: Please Check setAType() in setup()"<<endl;
		}
		areasIterator++;
		//areasIterator->Render(0.0,0.0,0.0);
		//areasIterator++;
	}
}

void drawAITRoads(void)
{
	roadsIterator = roads.begin();
	while(roadsIterator != roads.end())
	{
		roadsIterator->Render(X_Pos_Enter_Area,Y_Pos_Enter_Area,Z_Pos_Enter_Area);
		/*if(roadsIterator->getRtype() == ENTER_ATYPE)
		{
			roadsIterator->Render(X_Pos_Enter_Area,Y_Pos_Enter_Area,Z_Pos_Enter_Area);
		}else if(roadsIterator->getRtype() == A1_ATYPE){
			roadsIterator->Render(X_Pos_A1_Area,Y_Pos_A1_Area,Z_Pos_A1_Area);
		}else if(roadsIterator->getRtype() == A2_ATYPE){
			roadsIterator->Render(X_Pos_A2_Area,Y_Pos_A2_Area,Z_Pos_A2_Area);
		}else if(roadsIterator->getRtype() == A3_ATYPE){
			roadsIterator->Render(X_Pos_A3_Area,Y_Pos_A3_Area,Z_Pos_A3_Area);
		}else if(roadsIterator->getRtype() == A4_ATYPE){
			roadsIterator->Render(X_Pos_A4_Area,Y_Pos_A4_Area,Z_Pos_A4_Area);
		}else if(roadsIterator->getRtype() == A5_ATYPE){
			roadsIterator->Render(X_Pos_A5_Area,Y_Pos_A5_Area,Z_Pos_A5_Area);
		}else if(roadsIterator->getRtype() == A6_ATYPE){
			roadsIterator->Render(X_Pos_A6_Area,Y_Pos_A6_Area,Z_Pos_A6_Area);
		}else{
			cout<< "Area Type Have NONE TYPE at "<< areasIterator <<":: Please Check setAType() in setup()"<<endl;
		}*/
		roadsIterator++;
	}
}

// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{
   cout << "Interaction:" << endl;
}

// OpenGL window reshape routine.
void resize(int w, int h)
{
   glViewport(0, 0, (GLsizei)w, (GLsizei)h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(60.0, (float)w/(float)h, 1.0, 1000.0);
   glMatrixMode(GL_MODELVIEW);
}

// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
   switch(key) 
   {
      case 27:
         exit(0);
         break;
			case ' ': // Press spacebar for change view ( 1 = wire, 0 = filled)
         if (isWire == 0) isWire = 1; //wirefrime view
         else isWire = 0; //fill view
         glutPostRedisplay();
         break;
			case 'x':
         Xangle += 5.0;
		 if (Xangle > 360.0) Xangle -= 360.0;
         glutPostRedisplay();
         break;
      case 'X':
         Xangle -= 5.0;
		 if (Xangle < 0.0) Xangle += 360.0;
         glutPostRedisplay();
         break;
      case 'y':
         Yangle += 5.0;
		 if (Yangle > 360.0) Yangle -= 360.0;
         glutPostRedisplay();
         break;
      case 'Y':
         Yangle -= 5.0;
		 if (Yangle < 0.0) Yangle += 360.0;
         glutPostRedisplay();
         break;
      case 'z':
         Zangle += 5.0;
		 if (Zangle > 360.0) Zangle -= 360.0;
         glutPostRedisplay();
         break;
      case 'Z':
         Zangle -= 5.0;
		 if (Zangle < 0.0) Zangle += 360.0;
         glutPostRedisplay();
         break;
      default:
         break;
   }
}

void setupArea(void)
{
	//int Atype = ENTER_ATYPE;
	AITArea EnterArea;

	//for test if have many area
	AITArea A1Area,A2Area,A3Area,A4Area,A5Area,A6Area;//,A7Area;

	//create AIT area

	//enter area
	EnterArea.Intial(Enter_WArea,Enter_HArea,ENTER_ATYPE); 
	//EnterArea.setAType(ENTER_ATYPE);
	areas.push_back(EnterArea); 

	//A1 area For test if many area
	A1Area.Intial(A1_WArea,A1_HArea,A1_ATYPE); 
	//A1Area.setAType(A1_ATYPE);
	areas.push_back(A1Area);

	//A2 area For test if many area
	A2Area.Intial(A2_WArea,A2_HArea,A2_ATYPE); 
	//A2Area.setAType(A2_ATYPE);
	areas.push_back(A2Area);

	//A3 area For test if many area
	A3Area.Intial(A3_WArea,A3_HArea,A3_ATYPE); 
	areas.push_back(A3Area);

	//A4 area For test if many area
	A4Area.Intial(A4_WArea,A4_HArea,A4_ATYPE); 
	areas.push_back(A4Area);

	//A5 area For test if many area
	A5Area.Intial(A5_WArea,A5_HArea,A5_ATYPE); 
	areas.push_back(A5Area);

	//A6 area For test if many area
	A6Area.Intial(A6_WArea,A6_HArea,A6_ATYPE); 
	areas.push_back(A6Area);

	//A7 area For test if many area
	//A7Area.Intial(A7_WArea,A7_HArea,A7_ATYPE); 
	//areas.push_back(A7Area);
}

//Setup Road
void setupRoad()
{
	Road EnterR;

	EnterR.Initial(WEnterR,ENTER_ATYPE,EnterNumberPoint,EnterRoadMPoints,Enter_WArea,Enter_HArea,Leftcontrols,Rightcontrols);
	roads.push_back(EnterR);
}

// Initialization routine.
void setup(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
  glEnable(GL_DEPTH_TEST);
	
	setupArea();
	setupRoad();
}

// Drawing routine.
void drawScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Change to wire (1) or filled (0) View. 
	if (isWire) 
		glPolygonMode(GL_FRONT, GL_LINE);
	else 
		glPolygonMode(GL_FRONT, GL_FILL);

  glLoadIdentity();

	//gluLookAt(0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	gluLookAt(0.0, 150.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);

	// Rotate scene.
  glRotatef(Zangle, 0.0, 0.0, 1.0);
  glRotatef(Yangle, 0.0, 1.0, 0.0);
  glRotatef(Xangle, 1.0, 0.0, 0.0);

	glPushMatrix();
	glRotatef(90.0, -1.0, 0.0, 0.0);
	drawAITAreas();
	glPopMatrix();

	glPushMatrix();
	glRotatef(90.0, -1.0, 0.0, 0.0);
	drawAITRoads();
	glPopMatrix();

	glutSwapBuffers();
}

void main(void)
{
	printInteraction();
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("AITCarDriving");
	setup();
	glutDisplayFunc(drawScene);
	glutReshapeFunc(resize);
	glutKeyboardFunc(keyInput);
	glutMainLoop();
}